home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / mail / pine3.96.tar.gz / pine3.96.tar / pine3.96 / imap / ANSI / c-client / dummy.c < prev    next >
C/C++ Source or Header  |  1996-05-15  |  16KB  |  608 lines

  1. /*
  2.  * Program:    Dummy routines
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    9 May 1991
  13.  * Last Edited:    15 May 1995
  14.  *
  15.  * Copyright 1995 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35.  
  36.  
  37. #include <stdio.h>
  38. #include <ctype.h>
  39. #include <errno.h>
  40. extern int errno;        /* just in case */
  41. #include "mail.h"
  42. #include "osdep.h"
  43. #include <pwd.h>
  44. #include <sys/stat.h>
  45. #include "dummy.h"
  46. #include "misc.h"
  47.  
  48. /* Dummy routines */
  49.  
  50.  
  51. /* Driver dispatch used by MAIL */
  52.  
  53. DRIVER dummydriver = {
  54.   "dummy",            /* driver name */
  55.   (DRIVER *) NIL,        /* next driver */
  56.   dummy_valid,            /* mailbox is valid for us */
  57.   dummy_parameters,        /* manipulate parameters */
  58.   dummy_find,            /* find mailboxes */
  59.   dummy_find_bboards,        /* find bboards */
  60.   dummy_find_all,        /* find all mailboxes */
  61.   dummy_find_all_bboards,    /* find all bboards */
  62.   dummy_subscribe,        /* subscribe to mailbox */
  63.   dummy_unsubscribe,        /* unsubscribe from mailbox */
  64.   dummy_subscribe_bboard,    /* subscribe to bboard */
  65.   dummy_unsubscribe_bboard,    /* unsubscribe from bboard */
  66.   dummy_create,            /* create mailbox */
  67.   dummy_delete,            /* delete mailbox */
  68.   dummy_rename,            /* rename mailbox */
  69.   dummy_open,            /* open mailbox */
  70.   dummy_close,            /* close mailbox */
  71.   dummy_fetchfast,        /* fetch message "fast" attributes */
  72.   dummy_fetchflags,        /* fetch message flags */
  73.   dummy_fetchstructure,        /* fetch message structure */
  74.   dummy_fetchheader,        /* fetch message header only */
  75.   dummy_fetchtext,        /* fetch message body only */
  76.   dummy_fetchbody,        /* fetch message body section */
  77.   dummy_setflag,        /* set message flag */
  78.   dummy_clearflag,        /* clear message flag */
  79.   dummy_search,            /* search for message based on criteria */
  80.   dummy_ping,            /* ping mailbox to see if still alive */
  81.   dummy_check,            /* check for new messages */
  82.   dummy_expunge,        /* expunge deleted messages */
  83.   dummy_copy,            /* copy messages to another mailbox */
  84.   dummy_move,            /* move messages to another mailbox */
  85.   dummy_append,            /* append string message to mailbox */
  86.   dummy_gc            /* garbage collect stream */
  87. };
  88.  
  89.                 /* prototype stream */
  90. MAILSTREAM dummyproto = {&dummydriver};
  91.  
  92. /* Dummy validate mailbox
  93.  * Accepts: mailbox name
  94.  * Returns: our driver if name is valid, NIL otherwise
  95.  */
  96.  
  97. DRIVER *dummy_valid (char *name)
  98. {
  99.   char *s,tmp[MAILTMPLEN];
  100.   struct stat sbuf;
  101.                 /* must be valid local mailbox */
  102.   return (name && *name && (*name != '*') && (*name != '{') &&
  103.       (s = mailboxfile (tmp,name)) &&
  104.                 /* INBOX or empty file accepted */
  105.       (!*s || (!(stat (s,&sbuf) || sbuf.st_size))))
  106.     ? &dummydriver : NIL;
  107. }
  108.  
  109.  
  110. /* Dummy manipulate driver parameters
  111.  * Accepts: function code
  112.  *        function-dependent value
  113.  * Returns: function-dependent return value
  114.  */
  115.  
  116. void *dummy_parameters (long function,void *value)
  117. {
  118.   return NIL;
  119. }
  120.  
  121. /* Dummy find list of subscribed mailboxes
  122.  * Accepts: mail stream
  123.  *        pattern to search
  124.  */
  125.  
  126. void dummy_find (MAILSTREAM *stream,char *pat)
  127. {
  128.   void *s = NIL;
  129.   char *t;
  130.   if (*pat == '{') return;    /* local only */
  131.   if (t = sm_read (&s)) {     /* if have subscription database */
  132.     do if ((*t != '{') && (*t != '*') && pmatch (t,pat)) mm_mailbox (t);
  133.     while (t = sm_read (&s));    /* until no more subscriptions */
  134.   }
  135. }
  136.  
  137.  
  138. /* Dummy find list of subscribed bboards
  139.  * Accepts: mail stream
  140.  *        pattern to search
  141.  */
  142.  
  143. void dummy_find_bboards (MAILSTREAM *stream,char *pat)
  144. {
  145.   void *s = NIL;
  146.   char *t,tmp[MAILTMPLEN];
  147.   if (*pat == '{') return;    /* local only */
  148.                 /* no-op if have a subscription database */
  149.   if (t = sm_read (&s)) {    /* if have subscription database */
  150.     do if ((*t == '*') && (t[1] != '{') && pmatch (t+1,pat)) mm_bboard (t+1);
  151.     while (t = sm_read (&s));    /* read subscription database */
  152.   }
  153. }
  154.  
  155. /* Dummy find list of all mailboxes
  156.  * Accepts: mail stream
  157.  *        pattern to search
  158.  */
  159.  
  160. void dummy_find_all (MAILSTREAM *stream,char *pat)
  161. {
  162.   DIR *dirp;
  163.   struct direct *d;
  164.   char tmp[MAILTMPLEN],file[MAILTMPLEN];
  165.   char *s,*t;
  166.   int i = 0;
  167.   if (*pat == '{') return;    /* local only */
  168.   if (s = strrchr (pat,'/')) {    /* directory specified in pattern? */
  169.     strncpy (file,pat,i = (++s) - pat);
  170.     file[i] = '\0';        /* tie off prefix */
  171.                 /* make fully-qualified file name */
  172.     if (!(t = dummy_file (tmp,pat))) return;
  173.                 /* tie off directory name */
  174.     if (s = strrchr (t,'/')) *s = '\0';
  175.   }
  176.   else t = myhomedir ();    /* use home directory to search */
  177.   if (dirp = opendir (t)) {    /* now open that directory */
  178.     while (d = readdir (dirp))    /* for each directory entry */
  179.       if ((d->d_name[0] != '.') ||
  180.       (d->d_name[1] && ((d->d_name[1] != '.') || d->d_name[2]))) {
  181.     strcpy (file + i,d->d_name);
  182.     if (pmatch (file,pat)) mm_mailbox (file);
  183.       }
  184.     closedir (dirp);        /* flush directory */
  185.   }
  186.                 /* always an INBOX */
  187.   if (pmatch ("INBOX",pat)) mm_mailbox ("INBOX");
  188. }
  189.  
  190. /* Dummy find list of all bboards
  191.  * Accepts: mail stream
  192.  *        pattern to search
  193.  */
  194.  
  195. void dummy_find_all_bboards (MAILSTREAM *stream,char *pat)
  196. {
  197.   DIR *dirp;
  198.   struct direct *d;
  199.   struct passwd *pw;
  200.   char tmp[MAILTMPLEN],file[MAILTMPLEN];
  201.   int i = 1;
  202.   char *s;
  203.                 /* local only */
  204.   if ((*pat == '{') || !((pw = getpwnam ("ftp")) && pw->pw_dir)) return;
  205.   file[0] = '*';        /* bboard designator */
  206.                 /* directory specified in pattern? */
  207.   if (s = strrchr (pat,'/')) strncpy (file + 1,pat,i += (++s) - pat);
  208.   file[i] = '\0';        /* tie off prefix */
  209.   sprintf (tmp,"%s/%s",pw->pw_dir,(file[1] == '/') ? file + 2 : file + 1);
  210.   if (dirp = opendir (tmp)) {    /* now open that directory */
  211.     while (d = readdir (dirp))    /* for each directory entry */
  212.       if ((d->d_name[0] != '.') ||
  213.       (d->d_name[1] && ((d->d_name[1] != '.') || d->d_name[2]))) {
  214.     strcpy (file + i,d->d_name);
  215.     if (pmatch (file + 1,pat)) mm_bboard (file + 1);
  216.       }
  217.     closedir (dirp);        /* flush directory */
  218.   }
  219. }
  220.  
  221. /* Dummy subscribe to mailbox
  222.  * Accepts: mail stream
  223.  *        mailbox to add to subscription list
  224.  * Returns: T on success, NIL on failure
  225.  */
  226.  
  227. long dummy_subscribe (MAILSTREAM *stream,char *mailbox)
  228. {
  229.   char tmp[MAILTMPLEN];
  230.   return sm_subscribe (dummy_file (tmp,mailbox));
  231. }
  232.  
  233.  
  234. /* Dummy unsubscribe to mailbox
  235.  * Accepts: mail stream
  236.  *        mailbox to delete from subscription list
  237.  * Returns: T on success, NIL on failure
  238.  */
  239.  
  240. long dummy_unsubscribe (MAILSTREAM *stream,char *mailbox)
  241. {
  242.   char tmp[MAILTMPLEN];
  243.   return sm_unsubscribe (dummy_file (tmp,mailbox));
  244. }
  245.  
  246.  
  247. /* Dummy subscribe to bboard
  248.  * Accepts: mail stream
  249.  *        bboard to add to subscription list
  250.  * Returns: T on success, NIL on failure
  251.  */
  252.  
  253. long dummy_subscribe_bboard (MAILSTREAM *stream,char *mailbox)
  254. {
  255.   return NIL;            /* always fails */
  256. }
  257.  
  258.  
  259. /* Dummy unsubscribe to bboard
  260.  * Accepts: mail stream
  261.  *        bboard to delete from subscription list
  262.  * Returns: T on success, NIL on failure
  263.  */
  264.  
  265. long dummy_unsubscribe_bboard (MAILSTREAM *stream,char *mailbox)
  266. {
  267.   return NIL;            /* always fails */
  268. }
  269.  
  270. /* Dummy create mailbox
  271.  * Accepts: mail stream
  272.  *        mailbox name to create
  273.  *        driver type to use
  274.  * Returns: T on success, NIL on failure
  275.  */
  276.  
  277. long dummy_create (MAILSTREAM *stream,char *mailbox)
  278. {
  279.   char tmp[MAILTMPLEN];
  280.   int fd;
  281.   if ((fd = open (dummy_file (tmp,mailbox),O_WRONLY|O_CREAT|O_EXCL,
  282.           (int) mail_parameters (NIL,GET_MBXPROTECTION,NIL))) < 0) {
  283.     sprintf (tmp,"Can't create mailbox %s: %s",mailbox,strerror (errno));
  284.     mm_log (tmp,ERROR);
  285.     return NIL;
  286.   }
  287.   close (fd);            /* close the file */
  288.   return T;            /* return success */
  289. }
  290.  
  291.  
  292. /* Dummy delete mailbox
  293.  * Accepts: mail stream
  294.  *        mailbox name to delete
  295.  * Returns: T on success, NIL on failure
  296.  */
  297.  
  298. long dummy_delete (MAILSTREAM *stream,char *mailbox)
  299. {
  300.   char tmp[MAILTMPLEN];
  301.   if (unlink (dummy_file (tmp,mailbox))) {
  302.     sprintf (tmp,"Can't delete mailbox %s: %s",mailbox,strerror (errno));
  303.     mm_log (tmp,ERROR);
  304.     return NIL;
  305.   }
  306.   return T;            /* return success */
  307. }
  308.  
  309.  
  310. /* Mail rename mailbox
  311.  * Accepts: mail stream
  312.  *        old mailbox name
  313.  *        new mailbox name
  314.  * Returns: T on success, NIL on failure
  315.  */
  316.  
  317. long dummy_rename (MAILSTREAM *stream,char *old,char *new)
  318. {
  319.   char tmp[MAILTMPLEN],tmpnew[MAILTMPLEN];
  320.   if (rename (dummy_file (tmp,old),dummy_file (tmpnew,new))) {
  321.     sprintf (tmp,"Can't rename mailbox %s: %s",old,strerror (errno));
  322.     mm_log (tmp,ERROR);
  323.     return NIL;
  324.   }
  325.   return T;            /* return success */
  326. }
  327.  
  328. /* Dummy open
  329.  * Accepts: stream to open
  330.  * Returns: stream on success, NIL on failure
  331.  */
  332.  
  333. MAILSTREAM *dummy_open (MAILSTREAM *stream)
  334. {
  335.   int fd;
  336.   char err[MAILTMPLEN],tmp[MAILTMPLEN];
  337.   struct stat sbuf;
  338.                 /* OP_PROTOTYPE call */
  339.   if (!stream) return &dummyproto;
  340.   err[0] = '\0';        /* no error message yet */
  341.                 /* can we open the file? */
  342.   if ((fd = open (dummy_file (tmp,stream->mailbox),O_RDONLY,NIL)) < 0) {
  343.                 /* no, error unless INBOX */
  344.     if (strcmp (ucase (strcpy (tmp,stream->mailbox)),"INBOX"))
  345.       sprintf (err,"%s: %s",strerror (errno),stream->mailbox);
  346.   }
  347.   else {            /* file had better be empty then */
  348.     fstat (fd,&sbuf);        /* sniff at its size */
  349.     close (fd);
  350.     if (sbuf.st_size)        /* bogus format if non-empty */
  351.       sprintf (err,"%s (file %s) is not in valid mailbox format",
  352.            stream->mailbox,tmp);
  353.   }
  354.   if (!stream->silent) {    /* only if silence not requested */
  355.     if (err[0]) mm_log (err,ERROR);
  356.     else {
  357.       mail_exists (stream,0);    /* say there are 0 messages */
  358.       mail_recent (stream,0);    /* and certainly no recent ones! */
  359.     }
  360.   }
  361.   return err[0] ? NIL : stream;    /* return success if no error */
  362. }
  363.  
  364.  
  365. /* Dummy close
  366.  * Accepts: MAIL stream
  367.  */
  368.  
  369. void dummy_close (MAILSTREAM *stream)
  370. {
  371.                 /* return silently */
  372. }
  373.  
  374. /* Dummy fetch fast information
  375.  * Accepts: MAIL stream
  376.  *        sequence
  377.  */
  378.  
  379. void dummy_fetchfast (MAILSTREAM *stream,char *sequence)
  380. {
  381.   fatal ("Impossible dummy_fetchfast");
  382. }
  383.  
  384.  
  385. /* Dummy fetch flags
  386.  * Accepts: MAIL stream
  387.  *        sequence
  388.  */
  389.  
  390. void dummy_fetchflags (MAILSTREAM *stream,char *sequence)
  391. {
  392.   fatal ("Impossible dummy_fetchflags");
  393. }
  394.  
  395.  
  396. /* Dummy fetch envelope
  397.  * Accepts: MAIL stream
  398.  *        message # to fetch
  399.  *        pointer to return body
  400.  * Returns: envelope of this message, body returned in body value
  401.  */
  402.  
  403. ENVELOPE *dummy_fetchstructure (MAILSTREAM *stream,long msgno,BODY **body)
  404. {
  405.   fatal ("Impossible dummy_fetchstructure");
  406.   return NIL;
  407. }
  408.  
  409.  
  410. /* Dummy fetch message header
  411.  * Accepts: MAIL stream
  412.  *        message # to fetch
  413.  * Returns: message header in RFC822 format
  414.  */
  415.  
  416. char *dummy_fetchheader (MAILSTREAM *stream,long msgno)
  417. {
  418.   fatal ("Impossible dummy_fetchheader");
  419.   return NIL;
  420. }
  421.  
  422. /* Dummy fetch message text (body only)
  423.  * Accepts: MAIL stream
  424.  *        message # to fetch
  425.  * Returns: message text in RFC822 format
  426.  */
  427.  
  428. char *dummy_fetchtext (MAILSTREAM *stream,long msgno)
  429. {
  430.   fatal ("Impossible dummy_fetchtext");
  431.   return NIL;
  432. }
  433.  
  434.  
  435. /* Dummy fetch message body as a structure
  436.  * Accepts: Mail stream
  437.  *        message # to fetch
  438.  *        section specifier
  439.  * Returns: pointer to section of message body
  440.  */
  441.  
  442. char *dummy_fetchbody (MAILSTREAM *stream,long m,char *sec,unsigned long *len)
  443. {
  444.   fatal ("Impossible dummy_fetchbody");
  445.   return NIL;
  446. }
  447.  
  448.  
  449. /* Dummy set flag
  450.  * Accepts: MAIL stream
  451.  *        sequence
  452.  *        flag(s)
  453.  */
  454.  
  455. void dummy_setflag (MAILSTREAM *stream,char *sequence,char *flag)
  456. {
  457.   fatal ("Impossible dummy_setflag");
  458. }
  459.  
  460.  
  461. /* Dummy clear flag
  462.  * Accepts: MAIL stream
  463.  *        sequence
  464.  *        flag(s)
  465.  */
  466.  
  467. void dummy_clearflag (MAILSTREAM *stream,char *sequence,char *flag)
  468. {
  469.   fatal ("Impossible dummy_clearflag");
  470. }
  471.  
  472. /* Dummy search for messages
  473.  * Accepts: MAIL stream
  474.  *        search criteria
  475.  */
  476.  
  477. void dummy_search (MAILSTREAM *stream,char *criteria)
  478. {
  479.                 /* return silently */
  480. }
  481.  
  482.  
  483. /* Dummy ping mailbox
  484.  * Accepts: MAIL stream
  485.  * Returns: T if stream alive, else NIL
  486.  * No-op for readonly files, since read/writer can expunge it from under us!
  487.  */
  488.  
  489. long dummy_ping (MAILSTREAM *stream)
  490. {
  491.   char tmp[MAILTMPLEN];
  492.   MAILSTREAM *test = mail_open (NIL,stream->mailbox,OP_PROTOTYPE);
  493.                 /* swap streams if looks like a new driver */
  494.   if (test && (test->dtb != stream->dtb))
  495.     test = mail_open (stream,strcpy (tmp,stream->mailbox),NIL);
  496.   return test ? T : NIL;
  497. }
  498.  
  499.  
  500. /* Dummy check mailbox
  501.  * Accepts: MAIL stream
  502.  * No-op for readonly files, since read/writer can expunge it from under us!
  503.  */
  504.  
  505. void dummy_check (MAILSTREAM *stream)
  506. {
  507.   dummy_ping (stream);        /* invoke ping */
  508. }
  509.  
  510.  
  511. /* Dummy expunge mailbox
  512.  * Accepts: MAIL stream
  513.  */
  514.  
  515. void dummy_expunge (MAILSTREAM *stream)
  516. {
  517.                 /* return silently */
  518. }
  519.  
  520. /* Dummy copy message(s)
  521.  * Accepts: MAIL stream
  522.  *        sequence
  523.  *        destination mailbox
  524.  * Returns: T if copy successful, else NIL
  525.  */
  526.  
  527. long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox)
  528. {
  529.   fatal ("Impossible dummy_copy");
  530.   return NIL;
  531. }
  532.  
  533.  
  534. /* Dummy move message(s)
  535.  * Accepts: MAIL stream
  536.  *        sequence
  537.  *        destination mailbox
  538.  * Returns: T if move successful, else NIL
  539.  */
  540.  
  541. long dummy_move (MAILSTREAM *stream,char *sequence,char *mailbox)
  542. {
  543.   fatal ("Impossible dummy_move");
  544.   return NIL;
  545. }
  546.  
  547. /* Dummy append message string
  548.  * Accepts: mail stream
  549.  *        destination mailbox
  550.  *        optional flags
  551.  *        optional date
  552.  *        stringstruct of message to append
  553.  * Returns: T on success, NIL on failure
  554.  */
  555.  
  556. long dummy_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
  557.            STRING *message)
  558. {
  559.   struct stat sbuf;
  560.   int fd = -1;
  561.   int e;
  562.   char tmp[MAILTMPLEN];
  563.   if ((strcmp (ucase (strcpy (tmp,mailbox)),"INBOX")) &&
  564.        ((fd = open (dummy_file (tmp,mailbox),O_RDONLY,NIL)) < 0)) {
  565.     if ((e = errno) == ENOENT) {/* failed, was it no such file? */
  566.       mm_notify (stream,"[TRYCREATE] Must create mailbox before append",NIL);
  567.       return NIL;
  568.     }
  569.     sprintf (tmp,"%s: %s",strerror (e),mailbox);
  570.     mm_log (tmp,ERROR);        /* pass up error */
  571.     return NIL;            /* always fails */
  572.   }
  573.   else if (fd >= 0) {        /* found file? */
  574.     fstat (fd,&sbuf);        /* get its size */
  575.     close (fd);            /* toss out the fd */
  576.     if (sbuf.st_size) {        /* non-empty file? */
  577.       sprintf (tmp,"Indeterminate mailbox format: %s",mailbox);
  578.       mm_log (tmp,ERROR);
  579.       return NIL;
  580.     }
  581.   }
  582.   return (*default_proto ()->dtb->append) (stream,mailbox,flags,date,message);
  583. }
  584.  
  585.  
  586. /* Dummy garbage collect stream
  587.  * Accepts: mail stream
  588.  *        garbage collection flags
  589.  */
  590.  
  591. void dummy_gc (MAILSTREAM *stream,long gcflags)
  592. {
  593.                 /* return silently */
  594. }
  595.  
  596. /* Dummy mail generate file string
  597.  * Accepts: temporary buffer to write into
  598.  *        mailbox name string
  599.  * Returns: local file string
  600.  */
  601.  
  602. char *dummy_file (char *dst,char *name)
  603. {
  604.   char *s = mailboxfile (dst,name);
  605.                 /* return our standard inbox */
  606.   return (s && !*s) ? strcpy (dst,sysinbox ()) : s;
  607. }
  608.